#include "QHistogram.h"
#include "QTFEditor.h"
#include "histogram.h"
#include <QtGui/QPainter>
#include <QtGui/QPainterPath>
#include <QtGui/QPen>
#include <QtGui/QImage>
#include <QtCore/QRect>
#include <QtGui/QResizeEvent>
#include <QtCore/QSize>
#include <QtGui/QBrush>
#include <QtGui/QMenu>
#include <cmath>
using namespace std;

QHistogram::QHistogram(QWidget *parent)
:QTFAbstractPanel(parent)
{
	this->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
	this->setMinimumSize(400,100);
	this->setMaximumHeight(300);

	m_histogramType = 1; 
	m_backgroundMesh = 1; // dot
	m_yTransform = 0; // linear
	//m_pHistogramData = m_pTFEditor->m_histogramData;
	initLayout();
	initMenu();
	changeStyle2Line();
	changeBM2DotLine();
	changeYT2Linear();
	m_panelName = QString("Histogram");
}

void QHistogram::initLayout()
{
	QTFAbstractPanel::initLayout(25,1,25,5);
}
void QHistogram::initMenu()
{
	m_optionMenu = new QMenu(this);
	QMenu	*styleMenu = new QMenu(tr("Style"),this);

	changeStyle2LineAct = new QAction(tr("Line"),this);
	changeStyle2LineAct->setCheckable(true);
	connect(changeStyle2LineAct, SIGNAL(triggered()), this, SLOT(changeStyle2Line()));	
	changeStyle2BarAct = new QAction(tr("Bar"),this);
	changeStyle2BarAct->setCheckable(true);
	connect(changeStyle2BarAct, SIGNAL(triggered()), this, SLOT(changeStyle2Bar()));	
	
	styleMenu->addAction(changeStyle2LineAct);
	styleMenu->addAction(changeStyle2BarAct);

	QMenu	*backgroundMeshMenu = new QMenu(tr("Background Grid"),this);
	changeBM2NoneAct = new QAction(tr("None"),this);
	changeBM2NoneAct->setCheckable(true);
	connect(changeBM2NoneAct, SIGNAL(triggered()), this, SLOT(changeBM2None()));
	changeBM2DotLineAct = new QAction(tr("Dot Line"),this);
	changeBM2DotLineAct->setCheckable(true);
	connect(changeBM2DotLineAct, SIGNAL(triggered()), this, SLOT(changeBM2DotLine()));
	backgroundMeshMenu->addAction(changeBM2NoneAct);
	backgroundMeshMenu->addAction(changeBM2DotLineAct);
	
	QMenu	*yTransformMenu = new QMenu(tr("Y Axis Transform"),this);
	changeYT2LinearAct = new QAction(tr("Linear"),this);
	changeYT2LinearAct->setCheckable(true);
	connect(changeYT2LinearAct, SIGNAL(triggered()), this, SLOT(changeYT2Linear()));
	changeYT2LogAct = new QAction(tr("Log_10"),this);
	changeYT2LogAct->setCheckable(true);
	connect(changeYT2LogAct, SIGNAL(triggered()), this, SLOT(changeYT2Log()));
	yTransformMenu->addAction(changeYT2LinearAct);
	yTransformMenu->addAction(changeYT2LogAct);	
	
	m_optionMenu->addMenu(styleMenu);
	m_optionMenu->addMenu(backgroundMeshMenu);
	m_optionMenu->addMenu(yTransformMenu);
}

void QHistogram::realPaintEvent(QPaintEvent *)
{
	QPainter painter(this);
	painter.drawImage(rect(),*m_panelImage);
	Histogram* histogram = m_pTFEditor->getHistogram();

	if(histogram != NULL)
	{
		if(m_histogramType == 2) //bar
		{
			painter.setBrush(QColor(255,255,0,150));//Qt::yellow);
			painter.setPen(Qt::blue);
			for(size_t x=0;x<histogram->getLength();++x)
			{
				float binheight = 1;
				if(m_yTransform == 1)
					binheight = 1e-5 + (log10((float)(*histogram)[x] + 1)/m_histogramMax) * m_binMaxHeight;
				else
					binheight = ((float)(*histogram)[x])/m_histogramMax * m_binMaxHeight;
				float xpos = (float)(m_panelLMargin + 1)+ (float)x * m_binWidth;
				float ypos = m_panelUMargin + m_panelHeight - binheight;
				QRect binobj(xpos,ypos,m_binWidth,binheight);
				painter.drawRect(binobj);
			}
		}
		else if(m_histogramType == 1) // curve
		{
			painter.setBrush(QColor(255,255,0,150));
			painter.setPen(Qt::blue);	
			QPainterPath path;
			path.moveTo(m_panelLMargin,m_panelUMargin+m_panelHeight);
			
			for(size_t x=0;x<histogram->getLength();++x)
			{
				float binheight = 1;
				if(m_yTransform == 1)
					binheight = 1e-5 + (log10((float)(*histogram)[x] + 1)/m_histogramMax) * m_binMaxHeight;
				else
					binheight = ((float)(*histogram)[x])/m_histogramMax * m_binMaxHeight;
				float xpos = (float)(m_panelLMargin)+ (float)x * m_binWidth + 0.5*m_binWidth;
				float ypos = m_panelUMargin + m_panelHeight - binheight;
				path.lineTo(xpos,ypos);
			}
			
			path.lineTo(rect().width()-m_panelRMargin,m_panelUMargin+m_panelHeight);
			painter.drawPath(path);
		}
	}
}
void QHistogram::updateHistogram()
{
	Histogram* histogram = m_pTFEditor->getHistogram();
	if(histogram != NULL)
	{
		m_histogramMax = -1e20;
		m_histogramMin =  1e20;
	
		m_binWidth = (float)(m_panelWidth - 2)/ histogram->getLength();
		m_binMaxHeight = 0.98*m_panelHeight;
		
		if(m_yTransform == 0) // linear
		{	
			for(size_t x=0;x<histogram->getLength();++x)
			{
				if(m_histogramMax < (*histogram)[x])
					m_histogramMax = (*histogram)[x];
				if(m_histogramMin > (*histogram)[x])
					m_histogramMin = (*histogram)[x];
			}
		}
		else if(m_yTransform == 1) // log
		{
			for(size_t x=0;x<histogram->getLength();++x)
			{
				if(m_histogramMax < log10((float)(*histogram)[x] + 1))
					m_histogramMax = log10((float)(*histogram)[x] + 1)+1e-10;
				if(m_histogramMin > log10((float)(*histogram)[x] + 1))
					m_histogramMin = log10((float)(*histogram)[x] + 1)+1e-10;
				
				if(fabs(m_histogramMin) < 1e-10)
					m_histogramMin = 1e-10;
			}
		}

		repaint();
	}
}

void QHistogram::updatePanelImage()
{
	QPainter painter(m_panelImage);
	m_panelImage->fill(qRgb(255, 255, 255));

	QPen pen1(Qt::black, 1);
	painter.setPen(pen1);
	painter.drawRect(m_panelLMargin,m_panelUMargin,m_panelWidth,m_panelHeight);
	
	if(m_backgroundMesh == 1) // mesh
	{
		QPen	pen2(Qt::gray,1);
		pen2.setStyle(Qt::DashLine);
		painter.setPen(pen2);
		
		QPointF	px1,px2,py1,py2;
		for(int x=1;x<10;++x)
		{
			px1 = QPointF(m_panelLMargin + ((float)m_panelWidth/10.0f) * x,m_panelUMargin);
			px2 = QPointF(m_panelLMargin + ((float)m_panelWidth/10.0f) * x,m_panelUMargin+m_panelHeight);
			painter.drawLine(px1,px2);
			
			py1 = QPointF(m_panelLMargin,m_panelUMargin+((float)m_panelHeight/10.0f) * x);
			py2 = QPointF(rect().width()-m_panelRMargin,m_panelUMargin+((float)m_panelHeight/10.0f) * x);
			painter.drawLine(py1,py2);
		}
	}
	updateHistogram();
}
void QHistogram::mousePressEvent(QMouseEvent* event)
{
	if(event->button() == Qt::RightButton)
	{
		m_optionMenu->exec(QCursor::pos());
	}
}
void QHistogram::changeStyle2Line()
{
	changeStyle2LineAct->setChecked(true);
	changeStyle2BarAct->setChecked(false);
	m_histogramType = 1;
	repaint();
}
void QHistogram::changeStyle2Bar()
{
	changeStyle2LineAct->setChecked(false);
	changeStyle2BarAct->setChecked(true);	
	m_histogramType = 2;
	repaint();
}
void QHistogram::changeBM2None()
{
	changeBM2NoneAct->setChecked(true);
	changeBM2DotLineAct->setChecked(false);		
	m_backgroundMesh = 0;
	updatePanelImage();
	repaint();
}
void QHistogram::changeBM2DotLine()
{
	changeBM2NoneAct->setChecked(false);
	changeBM2DotLineAct->setChecked(true);	
	m_backgroundMesh = 1;
	updatePanelImage();
	repaint();
}
void QHistogram::changeYT2Linear()
{
	changeYT2LinearAct->setChecked(true);
	changeYT2LogAct->setChecked(false);
	m_yTransform = 0;
	updateHistogram();
	repaint();
}
void QHistogram::changeYT2Log()
{
	changeYT2LinearAct->setChecked(false);
	changeYT2LogAct->setChecked(true);
	m_yTransform = 1;
	updateHistogram();
	repaint();
}
